package OpenID::Tester;
use strict;
use OpenID::Tester::Capabilities;
use Carp qw(croak);

# fields:
#   op_caps -- OpenID::Tester::Capabilities object
#   rp_caps -- ""
#   ua
#   op_base
#   rp_base

sub new {
    my ($class, %opts) = @_;
    my $self = bless {}, $class;

    # required fields
    for my $f (qw(ua)) {
        $self->{$f} = delete $opts{$f} or croak
            "Missing required field: $f\n";
    }

    # optional fields
    for my $f (qw(op_base rp_base)) {
        $self->{$f} = delete $opts{$f};
    }
    croak "Unknown opts: " . join(", ", keys %opts) if %opts;
    return $self;
}

sub ua { $_[0]{ua} }

sub op_base { $_[0]{op_base} or die "no op_base" }
sub rp_base { $_[0]{rp_base} or die "no rp_base" }

sub op_is_rp {
    my $self = shift;
    return $self->{op_base} eq $self->{rp_base};
}

# memoized, with the twist that we reuse the RP's caps as the OP's
# caps when we know they're the same.
sub op_caps {
    my $self = shift;
    return $self->{op_caps} if $self->{op_caps};
    return $self->{rp_caps} if $self->op_is_rp && $self->{rp_caps};
    return $self->{op_caps} = $self->_get_caps($self->{op_base});
}

# memoized, with the twist that we reuse the RP's caps as the OP's
# caps when we know they're the same.
sub rp_caps {
    my $self = shift;
    return $self->{rp_caps} if $self->{rp_caps};
    return $self->{op_caps} if $self->op_is_rp && $self->{op_caps};
    return $self->{rp_caps} = $self->_get_caps($self->{rp_base});
}

sub has_op_cap {
    my ($self, $cap) = @_;
    return $self->op_caps->has_cap($cap);
}

sub has_rp_cap {
    my ($self, $cap) = @_;
    return $self->rp_caps->has_cap($cap);
}

sub _get_caps {
    my ($self, $base) = @_;
    my $ua = $self->ua;
    my $url = "$base/caps";
    my $res = $ua->get($url);
    die "Failed to get $url\n" unless $res->is_success;
    my $ctype = $res->header("content-type") || "";
    die "Capabilities at $url are not content type text/plain (got $ctype)\n" unless
        $ctype =~ m!^text/plain\b!;
    my $content = $res->content;
    return OpenID::Tester::Capabilities->new($content);
}

1;

